// phalanx begin.hpp.cu header file

// Copyright (c) 2011 - 2011 Kohei Takahashi (Flast).
// Distributed under the MIT license. for more detail see COPYING.

// Emulating C++0x's begin

#ifndef IG_PHALANX_UTILITY_DETAIL_BEGIN_HPP_CU_ONCE_
#define IG_PHALANX_UTILITY_DETAIL_BEGIN_HPP_CU_ONCE_

#include <phalanx/config.hpp.cu>

#include <cstddef>

#include <phalanx/iterator/builtin_vector_iterator.hpp.cu>

#include <phalanx/type_traits/builtin_traits.hpp.cu>
#include <phalanx/type_traits/remove_const.hpp.cu>

#include <phalanx/utility/enable_if.hpp.cu>

namespace phalanx
{

// for sequence
template < typename Sequence >
PHALANX_CONFIG_DEFAULT_FUNCTION( true )
typename disable_if<
  is_builtin_vector< Sequence >,
  typename Sequence::iterator >::type
begin( Sequence &seq )
{ return seq.begin(); }

template < typename Sequence >
PHALANX_CONFIG_DEFAULT_FUNCTION( true )
typename disable_if<
  is_builtin_vector< Sequence >,
  typename Sequence::const_iterator >::type
begin( const Sequence &seq )
{ return seq.begin(); }

template < typename Sequence >
PHALANX_CONFIG_DEFAULT_FUNCTION( true )
typename disable_if<
  is_builtin_vector< Sequence >,
  typename Sequence::const_iterator >::type
cbegin( const Sequence &seq )
{ return begin( seq ); }

// for CUDA builtin vector types
template < typename vector >
PHALANX_CONFIG_DEFAULT_FUNCTION( true )
typename enable_if<
  is_builtin_vector< typename remove_const< vector >::type >,
  builtin_vector_iterator< vector > >::type
begin( vector &vec )
{ return builtin_vector_iterator< vector >( vec, 0 ); }

template < typename vector >
PHALANX_CONFIG_DEFAULT_FUNCTION( true )
typename enable_if<
  is_builtin_vector< vector >,
  builtin_vector_iterator< const vector > >::type
cbegin( const vector &vec )
{ return begin( vec ); }


// for array
template < typename T, ::std::size_t n_ >
PHALANX_CONFIG_DEFAULT_FUNCTION( true )
T *
begin( T ( &_array )[ n_ ] )
{ return _array; }

template < typename T, ::std::size_t n_ >
PHALANX_CONFIG_DEFAULT_FUNCTION( true )
const T *
cbegin( const T ( &_array )[ n_ ] )
{ return _array; }

} // namespace phalanx

#endif // IG_PHALANX_UTILITY_DETAIL_BEGIN_HPP_CU_ONCE_

